#ifndef RSIM_VECT3_H
#define RSIM_VECT3_H

/* --------------------------------------------------------------------------*
* File: Vect3.h                                                              *
* Authors: Kishor Bhalerao                                                   *
* Email : kishor8dm@gmail.com                                                *
* Contributors:                                                              *
* Email:                                                                     *
* copyright (c) 2010 Authors.                                                *
*                                                                            *
* This program is free software: you can redistribute it and/or modify it    *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or any later version.*
*                                                                            *
* This program is distributed in the hope that it will be useful, but        *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
* for more details. (http://www.gnu.org/licenses/)                           *
* -------------------------------------------------------------------------- */

#include "Vector.h"
#include "Utils.h"

namespace RSIM{

template <class T> class Matrix_;	

template <class T>
class Vect3_:public Vector_<T>{
	public:
		/** Allocate space */
		Vect3_();
		
		/** Set each value to val */
		explicit Vect3_(const T& val);				
		
		/** Specify each value explictly */
		Vect3_(const T& val1, const T& val2, const T& val3);
				
		/** Copy constructor */
		Vect3_(const Vect3_<T>&);
		
		void copy(const T *ptr);
		
		/** Copy constructor */
		Vect3_(const Matrix_<T>&);
		
		/** Copy constructor */
		Vect3_(const Vector_<T>&);
                
                void operator=(const Matrix_<T>& M);
		
		/** assign new values. Assumed that space is already allocated */
		void updVec(const T& v1, const T& v2, const T& v3);
		
		Vect3_(const T *ptr);

};

////////////////////////////////////////////////////////////////////////

template <class T>
void Vect3_<T>::operator=(const Matrix_<T>& M){
        const int& row = M.getNRow();
        const int& col = M.getNCol();
        if(col == 1 && row == 3){
                const double *ptr = M.Ptr();
                this->data_[0] = ptr[0];
                this->data_[1] = ptr[1];
                this->data_[2] = ptr[2];    
        }
        else{         
                cout<<"\nDimension mismatch:. From Vect3_::operator=(const Matrix& M). Exiting...\n";
                exit(0);
        }
}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const T *ptr):Vector_<T>(3){
	this->data_[0] = ptr[0];
	this->data_[1] = ptr[1];
	this->data_[2] = ptr[2];
}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_():Vector_<T>(3){}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const T& val):Vector_<T>(3,val){}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const T& val1, const T& val2, const T& val3):Vector_<T>(3){
	this->data_[0]=val1;this->data_[1]=val2;this->data_[2]=val3;
}

////////////////////////////////////////////////////////////////////////

template <class T>
void Vect3_<T>::updVec(const T& v1, const T& v2, const T& v3){
	this->data_[0]=v1;this->data_[1]=v2;this->data_[2]=v3;
}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const Vect3_<T>& V):Vector_<T>(3){
	const T *ptr = V.Ptr();
	this->data_[0]=ptr[0];
	this->data_[1]=ptr[1];
	this->data_[2]=ptr[2];
	this->isColVec_ = V.isColVector();
}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const Matrix_<T>& M):Vector_<T>(3){
	Utils::rsim_assert(M.getNElements()==3,
                          "Dimension mismatch:. From Vect3_::Vect3_(const Matrix& M). Exiting...\n");
		
	const T *ptr = M.Ptr();
	this->data_[0]=ptr[0];
	this->data_[1]=ptr[1];
	this->data_[2]=ptr[2];
	this->isColVec_ = (M.getNCol()==1);
}

////////////////////////////////////////////////////////////////////////

template <class T>
Vect3_<T>::Vect3_(const Vector_<T>& V):Vector_<T>(3){
	const T *ptr = V.Ptr();
	this->data_[0]=ptr[0];
	this->data_[1]=ptr[1];
	this->data_[2]=ptr[2];
	this->isColVec_ = V.isColVector();
}

////////////////////////////////////////////////////////////////////////

template <class T>
void Vect3_<T>::copy(const T *ptr){
	this->data_[0]=ptr[0];
	this->data_[1]=ptr[1];
	this->data_[2]=ptr[2];
}

////////////////////////////////////////////////////////////////////////

} // namespace RSIM

#endif
